package top.bulk.retry.service.impl;

import lombok.extern.slf4j.Slf4j;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
import top.bulk.retry.service.TestRetryService;

import java.time.LocalDateTime;

/**
 * @author 散装java
 * @date 2024-07-03
 */
@Service
@Slf4j
public class TestRetryServiceImpl implements TestRetryService {
    /**
     * 简单测试
     */
    @Override
    @Retryable(value = Exception.class, maxAttempts = 3, recover = "recoverMethod1")
    public String test1() {
        log.info("调用test1：{}", LocalDateTime.now());
        throw new RuntimeException("假设出现异常");
    }

    /**
     * 测试自定义退避略
     */
    @Override
    @Retryable(value = RuntimeException.class,
            maxAttempts = 5,
            recover = "recoverMethod2",
            // 设置退避策略, 首次重试后等待1秒，之后每次重试等待时间都会变为前一次的1.5倍，直到达到最大等待时间10秒
            backoff = @Backoff(delay = 1000, multiplier = 1.5, maxDelay = 10000))
    public String test2() {
        log.info("测试退避策略，调用test2：{}", LocalDateTime.now());
        throw new RuntimeException("假设出现异常");
    }

    /**
     * `@Retryable` 中的 recover 参数，会根据 方法的参数类型进行匹配，所以这里可以有多个 recover 方法
     * 但是，其中参数的入参，必须和 `@Retryable` 中 value 参数类型一致
     * <p>
     * 一般会做一些兜底的处理
     */
    @Recover
    public String recoverMethod(Exception e) {
        log.info("执行recoverMethod ：{}", e.getMessage());
        return "进入recoverMethod";
    }

    @Recover
    public String recoverMethod2(Exception e) {
        log.info("recoverMethod2 ：{}", e.getMessage());
        return "进入recoverMethod2";
    }
}
